package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tbit.main.constant.DaoParamConstant;
import com.tbit.main.dao.core.UserDao;
import com.tbit.main.pojo.*;
import com.tbit.main.pojo.VO.RideLogReqVO;
import com.tbit.main.pojo.VO.RideLogRespVO;
import com.tbit.main.pojo.VO.UserVO;
import com.tbit.main.remote.map.TXHttpClient;
import com.tbit.main.service.AccountService;
import com.tbit.main.service.RideLogService;
import com.tbit.main.service.UserService;
import com.tbit.main.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户
 *
 * @author Leon
 * 2019年11月13日 下午9:35:11
 */
@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    @Autowired
    private AccountService accountService;
    @Autowired
    private RideLogService rideLogService;

    @Override
    public Integer getDepositUserCount(Integer accountId, String currentDate) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("currentDate", currentDate);

        return userDao.getDepositUserCount(params);
    }

    @Override
    public Integer getDepositUserCountByAccountId(Integer accountId, String currentDate) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("currentDate", currentDate);
        return userDao.getDepositUserCountByAccountId(params);
    }

    @Override
    public Integer getDepositUserCountByAccountIds(List<Integer> accountId, String currentDate) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, StringUtil.getListString(accountId));
        params.put("currentDate", currentDate);
        return userDao.getDepositUserCountByAccountIds(params);
    }

    @Override
    public Integer getUserCount(Integer accountId) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);

        return userDao.getUserCount(params);
    }

    @Override
    public List<Map<String, Object>> getUserCountByAccountIds(List<Integer> accountId) {
        Map<String, Object> params = new HashMap<>(4);
        params.put(DaoParamConstant.accountId, StringUtil.getListString(accountId));

        return userDao.getUserCountByAccountIds(params);
    }

    @Override
    public User getByUserId(Integer userId) {
        return userDao.getByUserId(userId);
    }

    @Override
    public User getByPhone(Integer accountId, String phone) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("phone", phone);
        return userDao.getByPhone(params);
    }

    @Override
    public List<KVEntity> groupBySex(Integer accountId) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);

        return userDao.groupBySex(params);
    }

    @Override
    public List<KVEntity> groupByAge(Integer accountId) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);

        return userDao.groupByAge(params);
    }

    @Override
    public String getUserMoneyCount(Integer accountId) {
        return userDao.getUserMoneyCount(accountId);
    }

    @Override
    public String getUserMoneyCountByAccountId(List<Integer> accountId) {
        Map<String, Object> map = new HashMap<>();
        map.put(DaoParamConstant.accountId, StringUtil.getListString(accountId));
        return userDao.getUserMoneyCountByAccountId(map);
    }

    @Override
    public KVEntity getUserDepositCount(Integer accountId) {
        return userDao.getUserDepositCount(accountId);
    }

    @Override
    public KVEntity getUserDepositCountByAccountId(List<Integer> accountId) {
        Map<String, Object> map = new HashMap<>();
        map.put(DaoParamConstant.accountId, StringUtil.getListString(accountId));
        return userDao.getUserDepositCountByAccountId(map);
    }

    @Override
    public Integer getBrandUserCount(Integer accountId) {
        return userDao.getBrandUserCount(accountId);
    }

    @Override
    public Integer getBrandUserCountByAccountIds(List<Integer> accountId) {
        Map<String, Object> map = new HashMap<>();
        map.put(DaoParamConstant.accountId, StringUtil.getListString(accountId));
        return userDao.getBrandUserCountByAccountIds(map);
    }

    @Override
    public Integer newUser(Integer accountId, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);

        return userDao.newUser(params);
    }

    @Override
    public Integer getAccountIdByUserId(Integer userId) {
        return userDao.getAccountIdByUserId(userId);
    }

    @Override
    public List<User> getAccountIdIdNO(Integer accountId, String IdNO) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("idNO", IdNO);
        return userDao.getAccountIdIdNO(params);
    }

    @Override
    public List<User> getUserIds(List<Integer> userIds) {
        return CollUtil.isEmpty(userIds)
                ? Collections.emptyList()
                : userDao.getUserIds(StringUtil.getListString(userIds));
    }

    @Override
    public List<UserVO> queryPage(AccountUser loginUser, Integer userId, String phone, String name, String idNo, Integer rowCount,
                                  Integer pageNO, Integer nameAuth, Integer depositState, Long startTime, Long endTime,
                                  Integer mapType) {
        //查询参数
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", loginUser.getBrandId());
        params.put("name", name);
        params.put("idNo", idNo);
        params.put("phone", phone);
        params.put("start", (pageNO - 1) * rowCount);
        params.put("rowCount", rowCount);
        params.put("nameAuth", nameAuth);
        params.put("depositState", depositState);
        if (userId != null) {
            params.put("userIds", Collections.singletonList(userId));
        }
        if (startTime != null) {
            params.put("startTime", new Date(startTime));
        }
        if (endTime != null) {
            params.put("endTime", new Date(endTime));
        }
        List<UserVO> users = userDao.queryPage(params);
        if (CollectionUtils.isEmpty(users)) {
            return users;
        }
        for (UserVO user : users) {
            RideLog rideLog = rideLogService.getRecentOrderByUserId(user.getUserId());
            if (rideLog != null) {
                convertRideLogToUserVO(user, rideLog);
                RideLogReqVO rideLogReqVO = new RideLogReqVO();
                rideLogReqVO.setAccountId(rideLog.getAccountId());
                rideLogReqVO.setOrderNo(rideLog.getOrderNO());
                rideLogReqVO.setPhoneOrOrderNoOrUserCode(rideLog.getOrderNO());
                rideLogReqVO.setPageNo(1);
                rideLogReqVO.setPageSize(1);
                rideLogReqVO.setStartTime(rideLog.getStartTime());
                rideLogReqVO.setEndTime(rideLog.getEndTime());
                PageResult<RideLogRespVO> rideLogPage = rideLogService.getRideLogPage(rideLogReqVO);
                List<RideLogRespVO> list = rideLogPage.getList();
                for (RideLogRespVO rideLogRespVO : list) {
                    //借车位置 最终使用的是machineBorrowPos里的address
                    BorrowPosLog machineBorrowPos = rideLogRespVO.getMachineBorrowPos();
                    if (machineBorrowPos == null){
                        machineBorrowPos = new BorrowPosLog();
                    }
                    BorrowPosLog mobileBorrowPos = rideLogRespVO.getMobileBorrowPos();
                    if (mobileBorrowPos != null){
                        Double lonBorrow = mobileBorrowPos.getLon();
                        Double latBorrow = mobileBorrowPos.getLat();
                        machineBorrowPos.setAddress(TXHttpClient.getAddress(lonBorrow, latBorrow));
                    }else {
                        Double lonBorrow = machineBorrowPos.getLon();
                        Double latBorrow = machineBorrowPos.getLat();
                        machineBorrowPos.setAddress(TXHttpClient.getAddress(lonBorrow, latBorrow));
                    }
                    rideLogRespVO.setMachineBorrowPos(machineBorrowPos);
                    //还车位置
                    ReturnPosLog machineReturnPos = rideLogRespVO.getMachineReturnPos();
                    if (machineReturnPos == null){
                        machineReturnPos = new ReturnPosLog();
                    }
                    ReturnPosLog mobileReturnPos = rideLogRespVO.getMobileReturnPos();
                    if (mobileReturnPos != null){
                        Double lonReturn = mobileReturnPos.getLon();
                        Double latReturn = mobileReturnPos.getLat();
                        machineReturnPos.setAddress(TXHttpClient.getAddress(lonReturn, latReturn));
                    }else {
                        Double lonReturn = machineReturnPos.getLon();
                        Double latReturn = machineReturnPos.getLat();
                        machineReturnPos.setAddress(TXHttpClient.getAddress(lonReturn, latReturn));
                    }
                    rideLogRespVO.setMachineReturnPos(machineReturnPos);
                }
                user.setRideLogRespVOList(list);
            }
        }
        Set<Integer> collect = users.stream()
                .map(User::getAccountId)
                .collect(Collectors.toSet());
        List<Integer> accountIds = new ArrayList<>(collect);
        Map<Integer, String> brandNameMap = accountService.getAccountIds(accountIds).stream().collect(Collectors.toMap(Account::getAccountId, Account::getName));
        users.forEach(object -> {
            if (object.getRideMoney() == null) {
                object.setRideMoney(0);
            }
            object.setBrandName(brandNameMap.getOrDefault(object.getAccountId(), "-"));
        });
        return users;
    }

    void convertRideLogToUserVO(UserVO userVO, RideLog rideLog) {
        userVO.setOrderNO(rideLog.getOrderNO())
                .setUserCode(rideLog.getUserCode())
                .setFeeMoney(rideLog.getMoney())
                .setMileage(rideLog.getMileage())
                .setPayTime(rideLog.getPayTime());

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startTime = LocalDateTime.parse(rideLog.getStartTime(), formatter);
        LocalDateTime endTime;
        if (rideLog.getEndTime() != null){
            endTime = LocalDateTime.parse(rideLog.getEndTime(), formatter);
        }else {
            endTime = LocalDateTime.now();
        }

        // 计算两个LocalDateTime对象之间的差异，得到Duration对象
        Duration duration = Duration.between(startTime, endTime);

        // 从Duration对象中获取小时、分钟和秒
        long totalMinutes = duration.toMinutes();
        Long hours = totalMinutes / 60;
        Long minutes = totalMinutes % 60;
        long seconds = duration.getSeconds() % 60;

        // 输出格式化的时间差异，使用String.format来确保两位数显示
        userVO.setRideTime(String.format("%02d时%02d分%02d秒", hours, minutes, seconds));
    }
}
